This is a full application in Delphi (2.0) which illustrates how to use Delphi and OLE to connect to the application IMSI SDK server, load drawings, draw graphics on screen, get properties and scroll and zoom the drawings.


unit Preview;
 
interface
 
uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ComCtrls, ExtCtrls, FileCtrl, Menus, Grids, Buttons;
 
type
  TPreviewForm = class(TForm)
    ButtonQuit: TButton;
    LoadTCFile: TButton;
    OpenDrawingFileDialog: TOpenDialog;
    StatusBar: TStatusBar;
    ButtonZoomMinus: TButton;
    CBDisplayDrawingName: TComboBox;
    PaintBox1: TPaintBox;
    HorizontalScrollBar: TScrollBar;
    VerticalScrollBar: TScrollBar;
    Label2: TLabel;
    Label3: TLabel;
    ButtonZoomPlus: TButton;
    ButtonDraw: TButton;
    PopupMenu1: TPopupMenu;
    Circle1: TMenuItem;
    Line1: TMenuItem;
    ButtonNew: TButton;
    ButtonShowProperties: TButton;
    ButtonCircle: TSpeedButton;
    ButtonSpline: TSpeedButton;
    ButtonLine: TSpeedButton;
    ButtonStar: TSpeedButton;
    ButtonPickPoint: TSpeedButton;
    StatusBar1: TStatusBar;
 
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure ButtonQuitClick(Sender: TObject);
    procedure PaintBox1Paint(Sender: TObject);
    procedure LoadTCFileClick(Sender: TObject);
    procedure LoadTCFileMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure VerticalScrollBarScroll(Sender: TObject;
      ScrollCode: TScrollCode; var ScrollPos: Integer);
    procedure HorizontalScrollBarScroll(Sender: TObject;
      ScrollCode: TScrollCode; var ScrollPos: Integer);
    procedure ButtonZoomPlusClick(Sender: TObject);
    procedure ButtonZoomMinusClick(Sender: TObject);
    procedure ButtonZoomMouseDown(Sender: TObject;
      Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    procedure ButtonClearClick(Sender: TObject);
    procedure ButtonDrawClick(Sender: TObject);
    procedure ButtonNewClick(Sender: TObject);
    procedure Circle1Click(Sender: TObject);
    procedure Line1Click(Sender: TObject);
    procedure ButtonShowPropertiesClick(Sender: TObject);
    procedure PaintBox1DragOver(Sender, Source: TObject; X, Y: Integer;
      State: TDragState; var Accept: Boolean);
    procedure PaintBox1EndDrag(Sender, Target: TObject; X, Y: Integer);
    procedure ButtonLineClick(Sender: TObject);
    procedure ButtonCircleClick(Sender: TObject);
    procedure ButtonSplineClick(Sender: TObject);
    procedure ButtonStarClick(Sender: TObject);
    procedure ButtonPickPointClick(Sender: TObject);
    procedure PaintBox1StartDrag(Sender: TObject;
      var DragObject: TDragObject);
 
  private
    { Private declarations }
  public
    { Public declarations }
    SDKApp : Variant;  { the overall OLE application object }
    SDKViews: Variant; { the overall SDK  View object }
    TheView: Variant; { the particuler instance of the view }
    SDKDrawings : Variant; { the overall SDK Drawing }
    TheDrawing : Variant; { the particular instance of the drawing }
    Graphics, pIGraphic: Variant; { Graphic variants used for drawing on screen }
    TCFileName : String;
    ViewLeft, ViewTop, ViewWidth, ViewHeight: Double;  { View coordinates }
    ScrollCenterX, ScrollCenterY: Double; { Dead center for scrolling }
    ScrollRangeX, ScrollRangeY: Double; { Scroll range }
    xStart, yStart: Double;  { Coordinates of start point of draw object }
    DragStarted: Boolean;
    SplineStarted: Boolean;
    PointPicked: Boolean;
    SelectedGraphic: Variant;
    procedure LoadTheDrawing(FileName: String);
    procedure ViewSetScrollPos;
    procedure UpdateScrollParams;
    procedure ViewZoomBy(Factor: Double);
    procedure ViewScrollBy(DeltaX: Double; DeltaY: Double);
    procedure PaintBoxRePaint;
    procedure NewDrawing;
  end;
 
 
var
  PreviewForm: TPreviewForm;
 
implementation
 
{$R *.DFM}
 
uses OleAuto, PopUp, Properties;
 
function VarValid(AVar: Variant): Boolean;
begin
	Result := (VarType(AVar) <> varEmpty) and (not VarIsNull(AVar));
end;
 
procedure TPreviewForm.FormCreate(Sender: TObject);
begin
     SDKApp := NULL;
     SDKViews := NULL;
     TheView := NULL;
     SDKDrawings := NULL;
     TheDrawing := NULL;
     SelectedGraphic := NULL;
     { Create the  OLE link to the TC SDK Application as IN-PROC server}
     SDKApp := CreateOleObject('IMSIGX.Application');
     { to connect to TurboCad as Local Server use:
       SDKApp := CreateOleObject('TurboCAD.Application'); }
     SDKDrawings := SDKApp.Drawings;  { Get the Drawings Collection to hold our drawings }
     TCFileName := '';
     DragStarted := false;
     SplineStarted := false;
     PointPicked := false;
     NewDrawing;   { set up a new drawing }
end;
 
procedure TPreviewForm.FormDestroy(Sender: TObject);
begin
 
     if VarValid(TheView) then VarClear(TheView);
     if VarValid(SDKViews) then VarClear(SDKViews);
     if VarValid(pIGraphic) then VarClear(pIGraphic);
 
     if VarValid(TheDrawing) then
     begin
         TheDrawing.Close;
         VarClear(TheDrawing);
     end;
 
     if VarValid(SDKDrawings) then VarClear(SDKDrawings);
     if VarValid(SDKApp) then VarClear(SDKApp);
end;
 
procedure TPreviewForm.ButtonQuitClick(Sender: TObject);
begin
   close;
end;
 
procedure TPreviewForm.PaintBox1Paint(Sender: TObject);
begin
	 PaintBoxRePaint;
end;
 
procedure TPreviewForm.LoadTCFileClick(Sender: TObject);
var nItem: Integer;
begin
  { Turn off spline }
  SplineStarted := false;
  DragStarted := false;
 
  TCFileName := '';
  { load the drawing from a group of files in a directory }
  { First display Dialog file selection and choose from available files }
  if OpenDrawingFileDialog.Execute then
  begin
 
    TCFileName := OpenDrawingFileDialog.FileName;
    PreviewForm.Caption := OpenDrawingFileDialog.FileName;
    nItem := CBDisplayDrawingName.Items.Add(OpenDrawingFileDialog.FileName);
    CBDisplayDrawingName.ItemIndex := nItem;
    if pos('.tcw', TCFileName) > 2 then
       LoadTheDrawing(TCFileName);
 
    StatusBar.SimpleText := 'Right click on button, object or screen to see the code for the procedure';
  end;
end;
 
{ Note: this will be replaced by simple call to TheView.ZoomBy when it is }
{ added to the SDK. }
procedure TPreviewForm.ViewZoomBy(Factor: Double);
var
   CanvasDC: HDC;
   VCenterX, VCenterY: Double;
   ViewChanged: Boolean;
begin
    if VarValid(TheDrawing) and VarValid(TheView) then
    begin
        ViewChanged := False;
 
        { Obtain the Device Context for the PaintBox canvas. }
        CanvasDC := PaintBox1.Canvas.Handle;
        TheView.Update := False;  { Delay update until we tell it to. }
        TheView.DC := CanvasDC;
        TheView.MappingMode := MM_TEXT;
        TheView.FixedAspectRatio := TRUE;
 
        { See if we need to start over. }
        if (Factor <= 0.0) or ((ViewWidth = 0) and (ViewHeight = 0)) then
        begin
           { Factor <= 0.0 means reset.  Otherwise, initial settings. }
           TheView.ScreenLeft := 0.0;
           TheView.ScreenTop :=  0.0;
           TheView.ScreenWidth := PaintBox1.Width;
           TheView.ScreenHeight := PaintBox1.Height;
           TheView.ZoomToExtents;  { zoom to largest drawing area }
           ViewLeft := TheView.ViewLeft;
           ViewTop := TheView.ViewTop;
           ViewWidth := TheView.ViewWidth;
           ViewHeight := TheView.ViewHeight;
           ViewChanged := True;
        end;
 
        if (Factor > 0.0) and (Factor <> 1.0) then
        begin
           { Keep the center fixed, and change view coordinates. }
           VCenterX := ViewLeft + (ViewWidth/2.0);
           VCenterY := ViewTop - (ViewHeight/2.0);
           ViewWidth := ViewWidth / Factor;
           ViewHeight := ViewHeight / Factor;
           ViewLeft := VCenterX - (ViewWidth/2.0);
           ViewTop := VCenterY + (ViewHeight/2.0);
           ViewChanged := True;
        end;
 
        { Synchronize the view to our new location and zoom. }
        TheView.ViewLeft := ViewLeft;
        TheView.ViewTop := ViewTop;
        TheView.ViewWidth := ViewWidth;
        TheView.ViewHeight := ViewHeight;
 
        { Update display. }
        PaintBoxRePaint;
 
        { Keep scroll bars in sync. }
        if ViewChanged then UpdateScrollParams;
    end;
end;
 
{ this loads the drawing from the disk using IMSI SDK }
procedure  TPreviewForm.LoadTheDrawing(FileName: String);
const
  MM_TEXT = 1;
var
    var1, var2: Variant;
    canvasRect: TRect;
    EVar: String;
begin
   if VarValid(SDKApp) and (FileName <> '') then
   begin
       try
       begin
           var1 := null;
           var2 := null;
 
           PaintBox1.Canvas.Brush.Color := clWhite;
           canvasRect := Rect(0, 0, PaintBox1.Width, PaintBox1.Width);
           PaintBox1.Canvas.FillRect(canvasRect);
 
           {  Close any previous open drawings }
           if VarValid(TheView) then
           begin
              VarClear(TheView);
              TheView := NULL;
           end;
 
           if VarValid(SDKViews) then
           begin
              VarClear(SDKViews);
              SDKViews := NULL;
           end;
 
           if VarValid(TheDrawing) then
           begin
               TheDrawing.Close(false);
               VarClear(TheDrawing);
               TheDrawing := NULL;
           end;
 
           { open the graphic TCW file using the SDK method }
           TheDrawing := SDKDrawings.Open(FileName);
           SDKViews := TheDrawing.Views;
           TheView := SDKViews.Add();
 
           { now that we have the particular view for the drawing, call the our
             repaint procedure to handle the painting using the SDK, we set
             the new global coordinates to accomplish the painting }
           { ViewWidth = 0.0 and ViewHeight = 0.0 mean initial settings }
           ViewWidth := 0.0;
           ViewHeight := 0.0;
           ViewLeft := 0.0;
           ViewTop := 0.0;
 
           ViewZoomBy(0.0);   { Specifying 0.0 as the zoom factor redraws... }
       end;
       except
          on E:Exception do
              MessageDlg('Exception Occurred: ' + E.Message, mtInformation, [mbOk], 0);
       end;
   end;
end;
 
procedure TPreviewForm.LoadTCFileMouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
   if Button = mbRight then
   begin
       FormPopUp.Top := PreviewForm.ClientOrigin.Y + (Sender as TButton).Top + (Sender as TButton).Height + 5;
       FormPopUp.Left := (PreviewForm.ClientOrigin.X + (Sender as TButton).Left + X) - (FormPopUp.Width div 2);
       FormPopUp.SetFileName('LoadFile.rtf');
       FormPopUp.show;
   end;
 
end;
 
procedure TPreviewForm.PaintBox1MouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var vX, vY: Double;
    DispText: String;
begin
   if Button = mbRight then
   begin
       FormPopUp.Top := PreviewForm.ClientOrigin.Y + Y + (Sender as TPaintBox).Top + 5;
       FormPopUp.Left := (PreviewForm.ClientOrigin.X + X) - (FormPopUp.Width div 2);
       FormPopUp.SetFileName('CreateForm.rtf');
       FormPopUp.show;
   end;
   if Button = mbLeft then
   begin
      DispText :=  'X: ' + IntToStr(X) + '   Y: ' + IntToStr(Y);
      if VarValid(TheDrawing) and VarValid(TheView) then
      begin
         TheView.ScreenToView(X, Y, vX, vY);
         DispText := DispText + '   View -> X: ' + FloatToStr(vX) + '   Y: ' + FloatToStr(vY);
         DispText := DispText + '   VL: ' + FloatToStr(TheView.ViewLeft);
          {'  VT: ' + FloatToStr(TheView.ViewTop) + '  VW: ' + FloatToStr(TheView.ViewWidth) +
          '  VH: ' + FloatToStr(TheView.ViewHeight);
          }
         if ButtonCircle.Down then
         begin
             Graphics := TheDrawing.Graphics;  { get the graphic to start drawing }
             xStart := X;
             yStart := Y;
         end
         else if ButtonLine.Down then
         begin
         end;
 
      end;
      StatusBar.SimpleText := DispText;
   end;
end;
 
{ Should be called whenever Drawing's bounding box, or Viewport is changed. }
procedure TPreviewForm.UpdateScrollParams;
var
   VarDummy: Variant;
   BBox, BoxMin, BoxMax: Variant;
   X1, Y1, X2, Y2: Double;
   Delta1, Delta2: Double;
begin
    Label2.Visible := True;
    Label3.Visible := True;
 
    HorizontalScrollBar.Visible := True;
    HorizontalScrollBar.Min := 0;
    HorizontalScrollBar.Max := 32000;
    HorizontalScrollBar.LargeChange := 3200;
    HorizontalScrollBar.SmallChange := 320;
 
    VerticalScrollBar.Visible := True;
    VerticalScrollBar.Min := 0;
    VerticalScrollBar.Max := 32000;
    VerticalScrollBar.LargeChange := 3200;
    VerticalScrollBar.SmallChange := 320;
 
    { Arbitrary limits if all else fails. }
    ScrollCenterX := 0.0;
    ScrollCenterY := 0.0;
    ScrollRangeX := 1.0;
    ScrollRangeY := 1.0;
    if VarValid(TheDrawing) then
    begin
         X1 := ViewLeft;
         Y1 := ViewTop - ViewHeight;
         X2 := ViewLeft + ViewWidth;
         Y2 := ViewTop;
         try
             { Set ScrollCenter to center of drawing's graphics. }
             Graphics := TheDrawing.Graphics;
 
             TVarData(varDummy).VType := varError;
             TVarData(varDummy).VError := DISP_E_PARAMNOTFOUND;
             BBox := Graphics.CalcBoundingBox( VarDummy );
 
             if not BBox.Empty then
             begin
                BoxMin := BBox.Min;
                BoxMax := BBox.Max;
                X1 := BoxMin.X;
                Y1 := BoxMin.Y;
                X2 := BoxMax.X;
                Y2 := BoxMax.Y;
                ScrollCenterX := (X1 + X2)/2.0;
                ScrollCenterY := (Y1 + Y2)/2.0;
 
                { Set min and max for range to include current viewport. }
                if ViewLeft < X1 then X1 := ViewLeft;
                if (ViewTop - ViewHeight) < Y1 then Y1 := ViewTop - ViewHeight;
                if (ViewLeft + ViewWidth) > X2 then X2 := ViewLeft + ViewWidth;
                if ViewTop > Y2 then Y2 := ViewTop;
             end;
         except
         end;
 
         { Set ScrollRange based on largest area included. }
         Delta1 := ScrollCenterX - X1;
         Delta2 := X2 - ScrollCenterX;
         if Delta1 > Delta2 then ScrollRangeX := 2.0 * Delta1
         else ScrollRangeX := 2.0 * Delta2;
 
         Delta1 := ScrollCenterY - Y1;
         Delta2 := Y2 - ScrollCenterY;
         if Delta1 > Delta2 then ScrollRangeY := 2.0 *Delta1
         else ScrollRangeY := 2.0 * Delta2;
    end;
    ViewSetScrollPos;
end;
 
function MyRound(D: Double): Integer;
var
   ConvertString: String;
begin
     ConvertString := FloatToStrF(D, ffFixed, 18, 0);
     Result := StrToInt(ConvertString);
end;
 
procedure TPreviewForm.ViewSetScrollPos;
var
   VCenter: Double;
   IMax: Integer;
   DMax: Double;
   DPos: Double;
   IPos: Integer;
begin
     if ScrollRangeX > 0.0 then
     begin
          IMax := HorizontalScrollBar.Max;
          DMax := IMax;
          VCenter := ViewLeft + (ViewWidth / 2.0);
          DPos := (DMax / 2.0) +
              DMax * (VCenter - ScrollCenterX)/ScrollRangeX;
 
          if DPos <= 0.0 then IPos := 0
          else if DPos >= DMax then IPos := IMax
          else IPos := MyRound(DPos);
          HorizontalScrollBar.Position := IPos;
     end;
 
     if ScrollRangeY > 0.0 then
     begin
          IMax := VerticalScrollBar.Max;
          DMax := IMax;
          VCenter := ViewTop - (ViewHeight / 2.0);
          DPos := (DMax / 2.0) +
              DMax * (VCenter - ScrollCenterY)/ScrollRangeY;
 
          if DPos < 0.0 then IPos := 0
          else if DPos > DMax then IPos := IMax
          else IPos := MyRound(DPos);
          VerticalScrollBar.Position := IPos;
     end;
end;
 
procedure TPreviewForm.ViewScrollBy(DeltaX: Double; DeltaY: Double);
begin
    ViewLeft := ViewLeft + DeltaX;
    ViewTop := ViewTop + DeltaY;
    ViewZoomBy(1.0);
end;
 
procedure TPreviewForm.VerticalScrollBarScroll(Sender: TObject;
  ScrollCode: TScrollCode; var ScrollPos: Integer);
var
   Y, YOrig: Double;
   DPos, DMax: Double;
begin
    if VarValid(TheDrawing) and VarValid(TheView) then
    begin
        Y := ViewTop - (ViewHeight/2.0); { Center point of view. }
        YOrig := Y;
 
        case ScrollCode of
           scLineUp:   Y := Y + (ViewHeight/32.0);  { scroll in the +Y direction }
           scPageUp:   Y := Y + (ViewHeight/8.0);  { scroll in the +Y direction }
           scLineDown: Y := Y - (ViewHeight/32.0);  { scroll in the -Y direction }
           scPageDown: Y := Y - (ViewHeight/8.0);  { scroll in the -Y direction }
           scTrack:
               begin
                    DPos := ScrollPos;
                    DMax := VerticalScrollBar.Max;
                    Y := ScrollCenterY -
                      (DPos / DMax - 0.5) * ScrollRangeY;
               end
           else Exit;
        end;
 
        ViewScrollBy(0.0, Y - YOrig);
    end;
end;
 
procedure TPreviewForm.HorizontalScrollBarScroll(Sender: TObject;
  ScrollCode: TScrollCode; var ScrollPos: Integer);
var
   X, XOrig: Double;
   DPos, DMax: Double;
begin
    if VarValid(TheDrawing) and VarValid(TheView) then
    begin
        X := ViewLeft + (ViewWidth/2.0); { Center point of view. }
        XOrig := X;
 
        case ScrollCode of
           scLineUp:   X := X - (ViewWidth/32.0);  { scroll in the -X direction }
           scPageUp:   X := X - (ViewWidth/8.0);  { scroll in the -X direction }
           scLineDown: X := X + (ViewWidth/32.0);  { scroll in the +X direction }
           scPageDown: X := X + (ViewWidth/8.0);  { scroll in the +X direction }
           scTrack:
               begin
                    DPos := ScrollPos;
                    DMax := HorizontalScrollBar.Max;
                    X := ScrollCenterX +
                      (DPos / DMax - 0.5) * ScrollRangeX;
               end
           else Exit;
        end;
 
        ViewScrollBy(X - XOrig, 0.0);
    end;
end;
 
procedure TPreviewForm.ButtonZoomPlusClick(Sender: TObject);
begin
    { Turn off spline }
    SplineStarted := false;
    DragStarted := false;
 
    ViewZoomBy(1.414);
end;
 
procedure TPreviewForm.ButtonZoomMinusClick(Sender: TObject);
begin
    { Turn off spline }
    SplineStarted := false;
    DragStarted := false;
 
    ViewZoomBy(0.707);
end;
 
procedure TPreviewForm.ButtonZoomMouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
   if Button = mbRight then
   begin
       FormPopUp.Top := PreviewForm.ClientOrigin.Y + (Sender as TButton).Top + (Sender as TButton).Height + 5;
       FormPopUp.Left := (PreviewForm.ClientOrigin.X + (Sender as TButton).Left + X) - (FormPopUp.Width div 2);
       FormPopUp.SetFileName('zoom.rtf');
       FormPopUp.show;
   end;
end;
 
{ This procedure repaints the screen with the current picture }
procedure TPreviewForm.PaintBoxRePaint;
const
  MM_TEXT = 1;
var CanvasDC: HDC;
    canvasRect: TRect;
    ViewChanged: Boolean;
begin
    { clear the screen to white first }
    canvasRect := Rect(0, 0, PaintBox1.Width, PaintBox1.Height);
    PaintBox1.Canvas.Brush.Color := clWhite;
    PaintBox1.Canvas.FillRect(canvasRect);
    if VarValid(TheDrawing) and VarValid(TheView) then
    begin
        { obtain the Device Context for the paintBox canvas }
        CanvasDC := PaintBox1.Canvas.Handle;
 
        TheView.Update := FALSE;  { delay update until we tell it to }
        TheView.DC := CanvasDC;
        TheView.MappingMode := MM_TEXT;
        TheView.FixedAspectRatio := TRUE;
 
        ViewChanged := (ViewWidth = 0) and (ViewHeight = 0);
        if ViewChanged then
        begin
           { Initial settings }
           TheView.ScreenLeft := canvasRect.Left;
           TheView.ScreenTop :=  canvasRect.Top;
           TheView.ScreenWidth := canvasRect.Right - canvasRect.Left;
           TheView.ScreenHeight := canvasRect.Bottom - canvasRect.Top;
           TheView.ZoomToExtents;
        end
        else
        begin
           { Saved settings }
           TheView.Refresh;
        end;
        ViewLeft := TheView.ViewLeft;
        ViewTop := TheView.ViewTop;
        ViewWidth := TheView.ViewWidth;
        ViewHeight := TheView.ViewHeight;
 
        if ViewChanged then UpdateScrollParams;
    end;
end;
 
procedure TPreviewForm.ButtonClearClick(Sender: TObject);
begin
  { clear the screen of the any drawing }
  PaintBox1.Canvas.Brush.Color := clWhite;
  PaintBox1.Canvas.FillRect(Rect(0, 0, PaintBox1.Width, PaintBox1.Height));
 
  { remove any Variant association and close the drawing }
  if VarValid(TheView) then
  begin
     VarClear(TheView);
     TheView := NULL;
  end;
 
  if VarValid(SDKViews) then
  begin
     VarClear(SDKViews);
     SDKViews := NULL;
  end;
 
  if VarValid(TheDrawing) then
  begin
      TheDrawing.Close(false);
      VarClear(TheDrawing);
      TheDrawing := NULL;
  end;
  UpdateScrollParams;
end;
 
procedure TPreviewForm.ButtonDrawClick(Sender: TObject);
begin
  { Turn off spline }
  SplineStarted := false;
  DragStarted := false;
 
  PopupMenu1.AutoPopup := False;
  PopupMenu1.Popup(PreviewForm.ClientOrigin.X + ButtonDraw.Left, PreviewForm.ClientOrigin.Y + ButtonDraw.Top + ButtonDraw.Height);
end;
 
procedure TPreviewForm.ButtonNewClick(Sender: TObject);
begin
   { Turn off spline }
   SplineStarted := false;
   DragStarted := false;
 
   if VarValid(SDKApp) then
   begin
      NewDrawing;   { set up a new drawing }
   end;
 
end;
 
procedure TPreviewForm.Circle1Click(Sender: TObject);
var
    xc, yc, zc, xp, yp, zp: double;
    vh, vw, vl, vt, vx, vy: double;
    vLeft, vTop: double;
begin
 
    { turn off spline and drag }
    SplineStarted := false;
    DragStarted := false;
 
    { Circle from center }
    { make sure that a drawing is ready for use }
    if VarValid(TheView) and VarValid(TheDrawing) then
    begin
 
        PaintBox1.Canvas.Brush.Color := clWhite;
        PaintBox1.Canvas.FillRect(Rect(0, 0, PaintBox1.Width, PaintBox1.Height));
 
        xc := (TheView.ViewLeft + TheView.ViewWidth) / 2.0;
        yc := (TheView.ViewTop - TheView.ViewHeight) / 2.0;
        zc := 0.0;
        xp := TheView.ViewLeft;
        yp := TheView.ViewTop;
        zp := 0.0;
 
        Graphics := TheDrawing.Graphics;
        pIGraphic := Graphics.AddCircleCenterAndPoint(xc, yc, zc, xp, yp, zp);
 
        PaintBoxRePaint;
        UpdateScrollParams;
    end;
end;
 
procedure TPreviewForm.Line1Click(Sender: TObject);
    { draw a line on screen }
var
    xc, yc, zc, xp, yp, zp: double;
    vh, vw, vl, vt: double;
begin
    { turn off spline and drag }
    SplineStarted := false;
    DragStarted := false;
 
   { Line from two points }
    { make sure that a drawing is ready for use }
    if VarValid(TheView) and VarValid(TheDrawing) then
    begin
        { clear screen first }
        PaintBox1.Canvas.Brush.Color := clWhite;
        PaintBox1.Canvas.FillRect(Rect(0, 0, PaintBox1.Width, PaintBox1.Height));
 
        { we need to draw in view coordinates not screen coordinates as the drawing
          by default is in inches. Remember that the default is: inches with the screen
          center as 0.0, 0.0}
        xc := (TheView.ViewWidth) / 2.0;;
        yc := 0.0;
        zc := 0.0;
        xp := (TheView.ViewLeft) + (TheView.ViewWidth / 2.0);
        yp := 0.0;
        zp := 0.0;
 
        xc := (TheView.ViewLeft + TheView.ViewWidth) / 2.0;
        yc := (TheView.ViewTop - TheView.ViewHeight) / 2.0;
        zc := 0.0;
        xp := TheView.ViewLeft;
        yp := TheView.ViewTop;
 
        Graphics := TheDrawing.Graphics;
        pIGraphic := Graphics.AddLineSingle(xc, yc, zc, xp, yp, zp);
 
        PaintBoxRePaint;
        UpdateScrollParams;
    end;
end;
 
procedure TPreviewForm.ButtonShowPropertiesClick(Sender: TObject);
var pItem, pProps, ValueStr: Variant;
    pTypeName, pName, TypeStr: String;
    pType: Integer;
    pValue: Variant;
    Count, ii, TotalWidth: Integer;
    isArray: Boolean;
    Col0, Col1, Col2: Integer;
begin
   if VarValid(SDKApp) then
   begin
       pProps := NULL;
       pProps := TheDrawing.Properties;
       Count := pProps.Count;
       Col0 := 0; Col1 := 0; Col2 := 0; TotalWidth := 0;
       with FormProperties.StringGridProperties do
       begin
          Cells[0, 0] := 'Property';
          if Canvas.TextWidth('Property') > Col0 then Col0 := Canvas.TextWidth('Property');
          Cells[1, 0] := 'Type';
          if Canvas.TextWidth('Type') > Col1 then Col1 := Canvas.TextWidth('Type');
          Cells[2, 0] := 'Value';
          if Canvas.TextWidth('Value') > Col2 then Col2 := Canvas.TextWidth('Value');
          RowCount := 1;
 
          for ii:=0 to Count-1 do
          begin
              { This is the way to access a property which takes a parameter }
              { Item(Parameter) must be used as an array Item[parameter] }
              pItem := pProps.Item[ii];
              RowCount := RowCount + 1;
              { get the name of the property }
              pName := pItem.Name;
 
              { find max width to set col, This uses the Canvas method TextWidth to
                find the string width in pixels }
              if Canvas.TextWidth(pName) > Col0 then Col0 := Canvas.TextWidth(pName);
 
              Cells[0, ii+1] := pName;
              { we need a try - exception here because the return may throw an exception on 'no value' }
              try
                 pType := pItem.Type;
                 isArray := False;
                 if (pType and varArray) <> 0 then
                 begin
                      isArray := True;
                      pType := pType and (not varArray);
                 end;
 
                 { we need to define what the TYPE means in english }
                 case pType of
                      varEmpty: { VT_EMPTY } pTypeName := 'Empty';
                      varSmallint: { VT_I2 } pTypeName := 'Integer';
                      varInteger: { VT_I4 } pTypeName := 'Long';
                      varSingle: { VT_R4 } pTypeName := 'Real';
                      varDouble: { VT_R8 } pTypeName := 'Double';
                      varOleStr: { VT_BSTR } pTypeName := 'String';
                      varBoolean: { VT_BOOL } pTypeName := 'Boolean';
                      varByte: { VT_UI1 } pTypeName := 'Byte';
                      else pTypeName := 'Unknown (' + IntToStr(pType) + ')';
                  end;
 
                  { if an array type then add extra wording }
                  if isArray then
                  begin
                     TypeStr := 'Array of ' + pTypeName;
                     Cells[1, ii+1] := TypeStr;
                     if Canvas.TextWidth(TypeStr) > Col1 then Col1 := Canvas.TextWidth(TypeStr);
                  end
                  else
                  begin
                     Cells[1, ii+1] := pTypeName;
                     if Canvas.TextWidth(pTypeName) > Col1 then Col1 := Canvas.TextWidth(pTypeName);
                  end;
 
              except
                  Cells[1, ii+1] := 'Error';
              end;
 
              try
                  PValue := pItem.Value;
                  if VarType(PValue) in [varSmallint, varInteger, varSingle, varDouble, varOleStr, varBoolean, varByte] then
                     VarCast (ValueStr, pValue, varString)   { convert to string }
                  else
                     ValueStr := 'Unknown';
 
                  Cells[2, ii+1] := ValueStr;
                  if Canvas.TextWidth(ValueStr) > Col2 then Col2 := Canvas.TextWidth(ValueStr);
              except
                  if Canvas.TextWidth('Error') > Col2 then Col2 := Canvas.TextWidth('Error');
                  Cells[2, ii+1] := 'Error';
              end;
 
          end;
 
 
          ColWidths[0] := Col0 + 5;
          ColWidths[1] := Col1 + 5;
          ColWidths[2] := Col2 + 5;
          TotalWidth := Col0 + Col1 + Col2 + 15;
          Width := TotalWidth + 25;
          FormProperties.Width := Width + 10;
          FixedRows := 1;
       end;
 
       FormProperties.show;
       VarClear(pProps);
       VarClear(pItem);
   end;
end;
 
procedure TPreviewForm.PaintBox1DragOver(Sender, Source: TObject; X,
  Y: Integer; State: TDragState; var Accept: Boolean);
var vX, vY: Double;
    DispText: String;
    TheStar: Variant;
begin
    DispText :=  'X: ' + IntToStr(X) + '   Y: ' + IntToStr(Y);
    if VarValid(TheView) then
    begin
       if not DragStarted then
       begin
          if (ButtonCircle.Down) or (ButtonLine.Down) or (ButtonStar.Down) or (ButtonPickPoint.Down) then
          begin
 
              { This starts the drawing fixing the first point as xStart and yStart }
              { first get the view coordinates from the screen coordinates of the
                mouse click }
              TheView.ScreenToView(X, Y, vX, vY);
              Graphics := TheDrawing.Graphics;  { get the graphic to start drawing }
              xStart := vX;
              yStart := vY;
              DragStarted := true;
 
              if ButtonPickPoint.Down then
                  PointPicked := true;
              { display in status box }
              DispText := DispText + '   View -> X: ' + FloatToStr(vX) + '   Y: ' + FloatToStr(vY);
              varClear(pIGraphic);
          end
          else if ButtonSpline.Down then
          begin
              if not SplineStarted then
              begin
                  TheView.ScreenToView(X, Y, vX, vY);
                  Graphics := TheDrawing.Graphics;  { get the graphic to start drawing }
                  xStart := vX;
                  yStart := vY;
                  DragStarted := true;
 
                  { display in status box }
                  DispText := DispText + '   View -> X: ' + FloatToStr(vX) + '   Y: ' + FloatToStr(vY);
              end;
          end
          else
          begin
              { no draw button down, so just display coordinates }
              TheView.ScreenToView(X, Y, vX, vY);
              DispText := DispText + '   View -> X: ' + FloatToStr(vX) + '   Y: ' + FloatToStr(vY);
          end;
       end
       else { still dragging the mouse }
       begin
 
          { if we wish to rubber bank the drawing object we have to erase the
            previous object and draw the temporary object from new positions }
 
          { just display the coordinates to the StatusBox }
          TheView.ScreenToView(X, Y, vX, vY);
          DispText := DispText + '   View -> X: ' + FloatToStr(vX) + '   Y: ' + FloatToStr(vY);
       end;
    end;
    { display coordinates of mouse to Status Box }
    StatusBar.SimpleText := DispText;
end;
 
{ This procedure shows how to draw on the screen in various way after a mouse click and move (drag) }
procedure TPreviewForm.PaintBox1EndDrag(Sender, Target: TObject; X, Y: Integer);
var  vX, vY: double;
     pickCount, ii: Integer;
     varX, varY, varZ: Double;
     varDummy, ThePickedResults: Variant;
     pIVertex, IVertices: Variant;
     TheItem, PickGraphic, ThePenColor, pProp: Variant;
 
begin
 
    if (DragStarted = true) and VarValid(TheView) and
       ((ButtonCircle.Down = true) or (ButtonLine.Down = true) or (ButtonSpline.Down = true) or
        (ButtonStar.Down = true) or (ButtonPickPoint.Down = true)) then
    begin
 
        { the user has now released the mouse button and we must draw the object with
          the coordinates from this mouse point }
 
        { clear the screen first. This would not be necessary if the drawing scale wasn't changing }
        PaintBox1.Canvas.Brush.Color := clWhite;
        PaintBox1.Canvas.FillRect(Rect(0, 0, PaintBox1.Width, PaintBox1.Height));
 
        { get the view coordinates for the screen mouse position }
        TheView.ScreenToView(X, Y, vX, vY);
 
        { with the start and ending coordinates we use the IMSI SDK to draw the circle line or slpine }
        if ButtonCircle.Down = true then { draw circle center and radius point }
            pIGraphic := Graphics.AddCircleCenterAndPoint(xStart, yStart, 0, vX, vY, 0)
        else if ButtonLine.Down = true then  { drawing line start and end point }
            pIGraphic := Graphics.AddLineSingle(xStart, yStart, 0, vX, vY, 0)
        else if ButtonSpline.Down = true then { draw spline, start point and subsequent mouse drag points }
        begin
            { First two points on spline come from draw Over and here from End drag }
            if not SplineStarted then { first time through with spline }
            begin
                varX := xStart;
                varY := yStart;
                varZ := 0.0;
                pIGraphic := Graphics.AddCurveSpline(varX, varY, 0.0);
                SplineStarted := true;  { mark as starting spline for subsequent mouse clicks and drags }
 
                TVarData(varDummy).VType := varError;
                TVarData(varDummy).VError := DISP_E_PARAMNOTFOUND;
 
                IVertices := NULL;
 	        IVertices := pIGraphic.Vertices;
                varX := vX;
                varY := vY;
                varZ := 0.0;
                pIVertex := NULL;
                {pIvertex := IVertices.Add(varX, varY, varZ, varDummy, varDummy, varDummy, varDummy, varDummy, varDummy, varDummy, varDummy);}
                pIvertex := IVertices.Add(varX, varY, varZ,,,,,,,,); { add a vertex. Delphi allows commas as place holder }
 
                if VarValid(pIVertex) then
                    VarClear(pIVertex);
 
                if VarValid(IVertices) then
                    VarClear(IVertices);
 
            end
            else
            begin
                TVarData(varDummy).VType := varError;
                TVarData(varDummy).VError := DISP_E_PARAMNOTFOUND;
 
                IVertices := NULL;
 	        IVertices := pIGraphic.Vertices;
                varX := vX;
                varY := vY;
                varZ := 0.0;
                pIVertex := NULL;
                {pIvertex := IVertices.Add(varX, varY, varZ, varDummy, varDummy, varDummy, varDummy, varDummy, varDummy, varDummy, varDummy);}
                pIvertex := IVertices.Add(varX, varY, varZ,,,,,,,,);
 
                if VarValid(pIVertex) then
                    VarClear(pIVertex);
 
                if VarValid(IVertices) then
                    VarClear(IVertices);
            end;
        end
        else if ButtonStar.Down = true then  { drawing Point, star, box or what ever }
        begin
{ !!!!!!!!!!!!!!!!!!!! FAILS AT DBAPI/DBD.cpp Line 2108 !!!!!!!!!!!!!!!!!!!!!!!!!!!!! }
            pIGraphic := Graphics.AddStar(xStart, yStart, 0.0);
        end
        else if (ButtonPickPoint.Down = true) and (PointPicked = true) then  { Pick point see if on graphic and highlite }
        begin
            try
                StatusBar1.SimpleText := 'Count: ';
                ThePickedResults := null;
                ThePickedResults := TheView.PickPoint(xStart, yStart,0.1,,,,,,);
 
                pickCount := ThePickedResults.Count;
                if pickCount > 0 then
                begin
                    { First deselect the current selected graphic if any }
                    if VarValid(SelectedGraphic) then
                    begin
                        PickGraphic := SelectedGraphic;
                        pProp := NULL;
                        pProp := PickGraphic.Properties;
 
                        ThePenColor := NULL;
                        ThePenColor := pProp.Item['PenColor'];
                        ThePenColor.Value :=  $000000;
                        VarClear(SelectedGraphic);
                        SelectedGraphic := NULL;
                    end;
 
                    for ii := 0 to pickCount - 1 do
                    begin
                        TheItem := ThePickedResults.Item[ii];  { must pass the parameter as if an array }
                        PickGraphic := TheItem.Graphic;
                        pProp := NULL;
                        pProp := PickGraphic.Properties;
 
                        ThePenColor := NULL;
                        ThePenColor := pProp.Item['PenColor'];
                        ThePenColor.Value :=  $0000FF;
 
                        SelectedGraphic := PickGraphic;
 
                        VarClear(TheItem);
                        VarClear(PickGraphic);
                        VarClear(ThePenColor);
                        VarClear(pProp);
 
                    end;
                    StatusBar1.SimpleText := 'Count: ' + IntToStr(pickCount);
                end;
 
 
 
                VarClear (ThePickedResults);
                PointPicked := false;
            except
               on E:Exception do
               begin
                   StatusBar1.SimpleText := 'Count: 0';
                   if VarValid(ThePickedResults) then
                       VarClear(ThePickedResults);
 
                   { do nothing as not graphic found at point }
               end;
            end;
        end;
 
        PaintBoxRePaint;
        UpdateScrollParams;
 
        { clear the graphics variant }
        if not SplineStarted then
        begin
           varClear(pIGraphic);
           DragStarted := false;
        end;
    end;
end;
 
procedure TPreviewForm.ButtonLineClick(Sender: TObject);
begin
   { draws a line from mouse down to mouse up }
    SplineStarted := false;
    DragStarted := false;
 
end;
 
procedure TPreviewForm.ButtonCircleClick(Sender: TObject);
begin
    StatusBar.SimpleText := 'Click and drag with mouse to draw circle';
    SplineStarted := false;
    DragStarted := false;
end;
 
procedure TPreviewForm.ButtonSplineClick(Sender: TObject);
begin
    SplineStarted := false;
    DragStarted := false;
end;
 
procedure TPreviewForm.ButtonStarClick(Sender: TObject);
begin
   { draw a Start. Could be any point object: point, circle, star, dot, square }
    SplineStarted := false;
    DragStarted := false;
end;
 
procedure TPreviewForm.ButtonPickPointClick(Sender: TObject);
begin
    { stop the spline if it is still waiting for points }
    SplineStarted := false;
    DragStarted := false;
    PointPicked := false; { start the picking by setting to false to clear any previous click }
end;
 
procedure TPreviewForm.NewDrawing;
const
    MM_TEXT = 1;
var
    var1, var2: Variant;
    canvasRect: TRect;
    EVar, DispText: String;
begin
    if VarValid(SDKApp) then
    begin
        try
        begin
            var1 := null;
            var2 := null;
 
            {  Close any previous open drawings }
            if VarValid(TheView) then
            begin
               VarClear(TheView);
               TheView := NULL;
            end;
 
            if VarValid(SDKViews) then
            begin
               VarClear(SDKViews);
               SDKViews := NULL;
            end;
 
            if VarValid(TheDrawing) then
            begin
                TheDrawing.Close(false);
                VarClear(TheDrawing);
                TheDrawing := NULL;
            end;
 
            { Get a new drawing using the SDK method }
            TheDrawing := SDKDrawings.Add;
            SDKViews := TheDrawing.Views;
            TheView := SDKViews.Add();
 
            { now that we have the particular view for the drawing, call the our
              repaint procedure to handle the painting using the SDK, we set
              the new global coordinates to accomplish the painting}
            ViewWidth := 0.0;{PaintBox1.Width;}
            ViewHeight := 0.0;{PaintBox1.Height; }
            ViewLeft := 0.0;
            ViewTop := 0.0;
 
            PaintBoxRePaint; { call the repaint procedure }
            UpdateScrollParams;
 
            DispText := 'VL: ' + FloatToStr(TheView.ViewLeft) +
             '  VT: ' + FloatToStr(TheView.ViewTop) + '  VW: ' + FloatToStr(TheView.ViewWidth) +
             '  VH: ' + FloatToStr(TheView.ViewHeight);
 
            StatusBar1.SimpleText := DispText;
        end;
        except
           on E:Exception do
               MessageDlg('Exception Occurred: ' + E.Message, mtInformation, [mbOk], 0);
        end;
    end;
end;
 
procedure TPreviewForm.PaintBox1StartDrag(Sender: TObject;
  var DragObject: TDragObject);
begin
    { unfortunately DragStart does not pass mouse coordinates so must use DragOver }
end;
 
end.